package cn.udrm.water.base.v1.administration.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.udrm.water.base.v1.administration.dto.AdministrationUnitDto;
import cn.udrm.water.base.v1.administration.dto.AdministrationUnitDtoMapper;
import cn.udrm.water.base.v1.administration.entities.AdministrationUnit;
import cn.udrm.water.base.v1.administration.repository.AdministrationUnitRepository;
import cn.udrm.water.base.v1.commons.models.PageModel;
import cn.udrm.water.base.v1.commons.models.ZTreeNodeVo;

@Service
@Transactional(readOnly=true)
public class AdministrationUnitService {
	@Autowired
	private AdministrationUnitRepository administrationUnitRepository;
	@Autowired
	private AdministrationUnitDtoMapper administrationUnitDtoMapper;
	
	/**
	 * 获取行政区划树
	 * @return
	 */
	public List<ZTreeNodeVo> getAdministrationUnitZtree() {
		List<AdministrationUnit> list = administrationUnitRepository.findAll();
		List<AdministrationUnitDto> from = administrationUnitDtoMapper.from(list);
		List<ZTreeNodeVo> treeNodeVos = new ArrayList<ZTreeNodeVo>(from.size());
		from.forEach((administrationUnitDto) -> {
			ZTreeNodeVo zTreeNodeVo = new ZTreeNodeVo(administrationUnitDto.getId(), administrationUnitDto.getName(), administrationUnitDto.getParentGuid());
			treeNodeVos.add(zTreeNodeVo);
		});
		return treeNodeVos;
	}
	
	/**
	 * 分页条件查询
	 * @param pageNumberStr
	 * @param pageSizeStr
	 * @param waterGateSearch
	 * @param sortField
	 * @param sortType
	 * @return
	 */
	public PageModel<AdministrationUnitDto> getPageByConditions(String pageNumberStr, String pageSizeStr, final AdministrationUnitDto administrationUnitSearch
			, String sortField, String sortType) {
		int number = 0,
			size = 0;
		try {
			number = Integer.parseInt(pageNumberStr);
		} catch (Exception e) {}
		try {
			size = Integer.parseInt(pageSizeStr);
		} catch (Exception e) {}
		size = size == 0 ? 10 : size;
		Sort sort = null;
		if (!StringUtils.isEmpty(sortField)) {
			try {
				sort = new Sort(StringUtils.isEmpty(sortType) ? Direction.ASC : (sortType.equals("ASC")) ? Direction.ASC : Direction.DESC, sortField);
			} catch (Exception e) {}
		} else {
			sort = new Sort(Direction.ASC, "createDate");
		}
		Pageable pageable = PageRequest.of(number, size, sort);
		Specification<AdministrationUnit> specification = new Specification<AdministrationUnit>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<AdministrationUnit> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				
				if (predicates.size() == 0) {
					return null;
				}
				Predicate predicateArr[] = new Predicate[predicates.size()];
				return cb.and(predicates.toArray(predicateArr));
			}
		};
		Page<AdministrationUnit> page = administrationUnitRepository.findAll(specification, pageable);
		List<AdministrationUnit> content = page.getContent();
		List<AdministrationUnitDto> dtos = administrationUnitDtoMapper.from(content);
		PageModel<AdministrationUnitDto> pageModel = new PageModel<AdministrationUnitDto>(page.getSize(), page.getNumber(), page.getTotalElements(), dtos);
		return pageModel;
	}
	
	public AdministrationUnitDto getAllById(String id) {
		AdministrationUnit administrationUnit = administrationUnitRepository.findAllById(id);
		List<AdministrationUnit> childrens = administrationUnit.getChildrens();
		AdministrationUnitDto administrationUnitDto = administrationUnitDtoMapper.from(administrationUnit);
		if (childrens != null) {
			List<AdministrationUnitDto> from = administrationUnitDtoMapper.from(childrens);
			administrationUnitDto.setAdministrationUnitDto(from);
		}
		return administrationUnitDto;
	}
	
	@Transactional(readOnly=false)
	public AdministrationUnitDto save(AdministrationUnitDto administrationUnitDto) {
		AdministrationUnit administrationUnit = administrationUnitDtoMapper.fromAdministrationUnitDto(administrationUnitDto);
		administrationUnit.setId(null);
		administrationUnit.setCreateDate(new Date());
		/*
		 * 设置父对象
		 */
		AdministrationUnit parent = null;
		String parentGuid = administrationUnitDto.getParentGuid();
		if (StringUtils.isNotBlank(parentGuid)) {
			parent = administrationUnitRepository.findAllById(parentGuid);
		}
		if (parent != null && StringUtils.isNotBlank(parent.getId())) {
			administrationUnit.setParent(parent);
		}
		administrationUnit = administrationUnitRepository.saveAndFlush(administrationUnit);
		AdministrationUnitDto dto = administrationUnitDtoMapper.from(administrationUnit);
		return dto;
	}
	@Transactional(readOnly=false)
	public AdministrationUnitDto update(AdministrationUnitDto administrationUnitDto) {
		AdministrationUnit administrationUnit = administrationUnitDtoMapper.fromAdministrationUnitDto(administrationUnitDto);
		/*
		 * 设置父对象
		 */
		AdministrationUnit parent = null;
		String parentGuid = administrationUnitDto.getParentGuid();
		if (StringUtils.isNotBlank(parentGuid)) {
			parent = administrationUnitRepository.findAllById(parentGuid);
		}
		if (parent != null && StringUtils.isNotBlank(parent.getId())) {
			administrationUnit.setParent(parent);
		}
		administrationUnit = administrationUnitRepository.saveAndFlush(administrationUnit);
		AdministrationUnitDto dto = administrationUnitDtoMapper.from(administrationUnit);
		return dto;
	}
	
	/**
	 * 删除所有信息, 包括其级联的所有实体
	 * @param ids
	 */
	@Transactional(readOnly=false)
	public void deleteAll(String[] ids) {
		if (ids == null || ids.length == 0) {
			return;
		}
		List<AdministrationUnit> administrationUnits = new ArrayList<AdministrationUnit>();
		for (String id : ids) {
			administrationUnits.add(new AdministrationUnit(id));
		}
		this.deleteAll(administrationUnits);
	}
	
	/**
	 * @param iterable
	 */
	@Transactional(readOnly=false)
	private void deleteAll(Iterable<AdministrationUnit> iterable) {
		if (iterable == null || iterable.iterator() == null) {
			return;
		}
		Iterator<AdministrationUnit> iterator = iterable.iterator();
		while (iterator.hasNext()) {
			AdministrationUnit administrationUnit = iterator.next();
			administrationUnit = administrationUnitRepository.findAllById(administrationUnit.getId());
			List<AdministrationUnit> childrens = administrationUnit.getChildrens();
			this.deleteAll(childrens);
			administrationUnitRepository.delete(administrationUnit);
		}
	}
	
	@Transactional(readOnly=false)
	public void deleteAllSelf(String[] ids) {
		if (ids == null || ids.length == 0) {
			return;
		}
		for (String id : ids) {
			administrationUnitRepository.deleteById(id);
		}
	}
}
